Support brick/money 0.14 - #24
Draft
robertvansteen wants to merge 2 commits into
Draft
Conversation
brick removed three APIs this package relied on and tightened a fourth: - Currency::is() is gone in favour of isEqualTo() (6 call sites). - AbstractMoney::to() is now toContext(). - Money::isAmountAndCurrencyEqualTo() is now isSameValueAs(), which is what the =, ==, === and their negations evaluate with. - RoundingMode cases are PascalCase, so HALF_UP reads HalfUp. The tightening that matters is floats. brick now rejects a float anywhere an exact amount is required, because a binary float has no exact decimal value — the literal 0.1 is not one tenth. The host language still hands us int|float scalars, so MoneyParser::exact renders one in the form brick accepts: a float becomes the shortest decimal that round-trips to it, which is the number the source text denoted; ints and numeric strings are already exact. Every boundary that reads a raw amount goes through it — scalar multiplication and division in MoneyExtension, the coercions in MonetaryType and MinorMonetaryType, and the locale-parsed amount in MoneyParser itself — so the rule lives in one place. format() took mixed and called Money methods on it unguarded. It now narrows through instance_of first, as the surrounding code does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The float conversion vouched for a guarantee it did not provide. PHP's `(string)` cast on a float honours `precision` — 14 significant digits by default — not `serialize_precision`, so it truncates and can emit exponent notation: `(string) 123456789012345.67` is `1.2345678901235E+14`, an amount the caller never held. `json_encode` honours `serialize_precision` (-1) and yields the shortest decimal that round-trips, which is what the docblock describes. Two provider cases pin it — one past 14 significant digits, one that is all float residue — and both fail on the old cast. A non-finite float names no decimal at all, so it is refused rather than silently encoded. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
brick removed three APIs this package relied on and tightened a fourth:
Currency::is()is gone in favour ofisEqualTo()(6 call sites).AbstractMoney::to()is nowtoContext().Money::isAmountAndCurrencyEqualTo()is nowisSameValueAs(), which is what=,==,===and their negations evaluate with.RoundingModecases are PascalCase, soHALF_UPreadsHalfUp.The tightening that matters is floats. brick now rejects a float anywhere an exact amount is required, because a binary float has no exact decimal value — the literal
0.1is not one tenth. The host language still hands usint|floatscalars, soMoneyParser::exactrenders one in the form brick accepts:A float becomes the shortest decimal that round-trips to it — the number the source text denoted — while ints and numeric strings are already exact. Every boundary that reads a raw amount goes through it: scalar multiplication and division in
MoneyExtension, the coercions inMonetaryTypeandMinorMonetaryType, and the locale-parsed amount inMoneyParseritself, so the rule lives in one place.format()tookmixedand calledMoneymethods on it unguarded. It now narrows throughinstance_offirst, as the surrounding code does.Verified against the local chain: PHPStan clean, 136 tests, 100% coverage, MSI 100%.